package com.tom.zx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tom.zx.entity.Menu;
import com.tom.zx.entity.MenuRole;
import com.tom.zx.entity.User;
import com.tom.zx.mapper.MenuMapper;
import com.tom.zx.mapper.MenuRoleMapper;
import com.tom.zx.mapper.UserMapper;
import com.tom.zx.service.IMenuService;
import com.tom.zx.vo.MenuVo;
import com.tom.zx.vo.ReturnDistributionVo;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 服务实现类
 *
 * @author 王妍
 * @since 2022-02-20
 */
@Service
@AllArgsConstructor
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

  private final MenuMapper menuMapper;

  private final MenuRoleMapper menuRoleMapper;

  private final UserMapper userMapper;

  @Override
  public MenuVo loadMenuByUserName(String userName) {
    Long userId =
        Optional.ofNullable(
                userMapper.selectOne(
                    new LambdaQueryWrapper<User>().eq(User::getUsername, userName)))
            .map(User::getId)
            .orElseThrow(() -> new UsernameNotFoundException("用户名没有！！！"));
    List<Menu> menuList = menuMapper.selectAllMenuByUserName(userId);
    final MenuVo menuVo = new MenuVo();
    menuVo.setId(-1L);
    createMenuTree(menuList, menuVo);
    return menuVo;
  }

  @Override
  public MenuVo getSubMenu(MenuVo menuVo) {
    createMenuTree(menuMapper.selectList(new QueryWrapper<>()), menuVo);
    return menuVo;
  }

  private void createMenuTree(List<Menu> menuList, MenuVo menuVo) {
    final List<Menu> menus =
        menuList.stream()
            .filter(menu -> menu.getParentId().equals(menuVo.getId()))
            .collect(Collectors.toList());
    final List<MenuVo> menuVoList =
        menus.stream()
            .map(
                menu -> {
                  final MenuVo tMenu = new MenuVo();
                  BeanUtils.copyProperties(menu, tMenu);
                  return tMenu;
                })
            .collect(Collectors.toList());
    menuVo.setChildMenus(menuVoList);
    menuVoList.forEach(menu -> createMenuTree(menuList, menu));
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void configureMenuForRole(Long roleId, List<Long> menuIds) {
    menuRoleMapper.delete(new LambdaQueryWrapper<MenuRole>().eq(MenuRole::getMenuId, roleId));
    final List<MenuRole> menuRoles =
        menuIds.stream()
            .map(
                menuId -> {
                  final MenuRole menuRole = new MenuRole();
                  menuRole.setRoleId(roleId);
                  menuRole.setMenuId(menuId);
                  return menuRole;
                })
            .collect(Collectors.toList());
    menuRoles.forEach(menuRoleMapper::insert);
  }

  @Override
  public ReturnDistributionVo<Menu> getMenuDistribution(Long roleId) {
    List<Menu> ownMenus = menuMapper.selectMenuByRoleId(roleId, true);
    final ReturnDistributionVo<Menu> distributionVo = new ReturnDistributionVo<Menu>();
    distributionVo.setOwnRoles(ownMenus.stream().map(Menu::getId).collect(Collectors.toList()));
    distributionVo.setAllRoles(list());
    return distributionVo;
  }
}
